import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.lang.reflect.Method;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

public class UiBuilder {
    
    public static final Map<String, Component> componentCacheMap = new HashMap<>();
    
    public static JComponent buildSwingComponent(String key, String simpleClassName) {
        return buildSwingComponent(key, simpleClassName, null, null, null);
    }
    
    public static JComponent buildSwingComponent(String key, String simpleClassName, Map<String, Object> otherProps) {
        return buildSwingComponent(key, simpleClassName, null, null, otherProps);
    }
    
    public static JComponent buildSwingComponent(String key, String simpleClassName, String title) {
        return buildSwingComponent(key, simpleClassName, title, null, Collections.emptyMap());
    }
    
    public static JComponent buildSwingComponent(String key, String simpleClassName, String title, ActionListener actionListener) {
        return buildSwingComponent(key, simpleClassName, title, actionListener, Collections.emptyMap());
    }
    
    public static JComponent buildSwingComponent(String key, String simpleClassName, String title, Map<String, Object> otherProps) {
        return buildSwingComponent(key, simpleClassName, title, null, otherProps);
    }
    
    public static JComponent buildSwingComponent(String key, String simpleClassName, String title, ActionListener actionListener, Map<String, Object> otherProps) {
        try {
            if (isBlank(key) || isBlank(simpleClassName)) {
                throw new RuntimeException("必要参数为空");
            }
            Class<?> clazz = Class.forName("javax.swing." + simpleClassName);
            Object component = clazz.newInstance();
            List<String> methodNames = Arrays.stream(clazz.getMethods()).map(Method::getName).collect(Collectors.toList());
            if (isNotBlank(title) && methodNames.contains("setTitle")) {
                clazz.getMethod("setTitle", String.class).invoke(component, title);
            }
            if (isNotBlank(title) && methodNames.contains("setText")) {
                clazz.getMethod("setText", String.class).invoke(component, title);
            }
            if (isNotBlank(title) && methodNames.contains("addActionListener")) {
                clazz.getMethod("addActionListener", ActionListener.class).invoke(component, actionListener);
            }
            if (Objects.nonNull(otherProps) && otherProps.size() > 0) {
                Set<String> otherPropSet = otherProps.keySet();
                for (String otherPropName : otherPropSet) {
                    String otherPropMethodName = "set" + otherPropName.substring(0, 1).toUpperCase() + otherPropName.substring(1);
                    if (isNotBlank(otherPropName) && methodNames.contains(otherPropMethodName)) {
                        Object otherPropVal = otherProps.get(otherPropName);
                        if (otherPropVal instanceof String) {
                            clazz.getMethod(otherPropMethodName, String.class).invoke(component, otherPropVal.toString());
                        }
                        if (otherPropVal instanceof Integer) {
                            try {
                                clazz.getMethod(otherPropMethodName, Integer.class).invoke(component, Integer.parseInt(otherPropVal.toString()));
                            } catch (NoSuchMethodException e) {
                                clazz.getMethod(otherPropMethodName, int.class).invoke(component, Integer.parseInt(otherPropVal.toString()));
                            }
                        }
                        if (otherPropVal instanceof Float) {
                            try {
                                clazz.getMethod(otherPropMethodName, Float.class).invoke(component, Float.parseFloat(otherPropVal.toString()));
                            } catch (NoSuchMethodException e) {
                                clazz.getMethod(otherPropMethodName, float.class).invoke(component, Float.parseFloat(otherPropVal.toString()));
                            }
                        }
                    }
                }
            }
            JComponent retComponent = (JComponent) component;
            componentCacheMap.put(key, retComponent);
            return retComponent;
        } catch (Exception e) {
            throw new RuntimeException("创建组件异常");
        }
    }
    
    public static boolean isNotBlank(String str) {
        if (str == null) {
            return false;
        }
        return str.trim().length() != 0;
    }
    
    public static boolean isBlank(String str) {
        return !isNotBlank(str);
    }
    
}
